<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
  <link href="//gmpg.org/xfn/11" rel="profile">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="generator" content="Hugo 0.68.3" />

  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>mysql基础相关 &middot; 我的博客</title>

  
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/print.css" media="print">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/poole.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/syntax.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/hyde.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abril+Fatface|PT+Sans:400,400i,700">


  
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="/favicon.png">

  
  
</head>

  <body class="theme-base-0b ">
  <aside class="sidebar">
  <div class="container sidebar-sticky">
    <div class="sidebar-about">
      <a href="/my_technology_blog/"><h1>我的博客</h1></a>
      <p class="lead">
       杨博的博客 
      </p>
    </div>

    <nav>
      <ul class="sidebar-nav">
        <li><a href="/my_technology_blog/">Home</a> </li>
        
      </ul>
    </nav>

    <p>&copy; 2021. All rights reserved. </p>
  </div>
</aside>

    <main class="content container">
    <div class="post">
  <h1>mysql基础相关</h1>
  <time datetime=2020-06-26T14:34:16&#43;0800 class="post-date">Fri, Jun 26, 2020</time>
  <h2 id="事物隔离级别">事物隔离级别</h2>
<p><strong>1 未提交读: 脏读（READ UNCOMMITTED）</strong></p>
<p>​	1）事务2查询到的数据是事务1中修改但未提交的数据，但因为事务1回滚了数据</p>
<p>​	2）所以事务2查询的数据是不正确的，因此出现了脏读的问题。</p>
<p><strong>2 提交读: 不可重复读（READ COMMITTED）</strong></p>
<p>​	1）事务2执行update语句但未提交前，事务1的前两个select操作返回结果是相同的。</p>
<p>​	2）但事务2执行commit操作后，事务1的第三个select操作就读取到事务2对数据的改变。</p>
<p>​	3）导致与前两次select操作返回不同的数据，因此出现了不可重复读的问题。</p>
<p><strong>3</strong> <strong>可重复读: 幻读（REPEATABLE READ）：这是MySQL的默认事务隔离级别</strong></p>
<p>​	1）事务每开启一个实例，都会分配一个版本号给它，如果读取的数据行正在被其它事务执行DELETE或UPDATE操作（即该行上有排他锁）</p>
<p>​	2）这时该事物的读取操作不会等待行上的锁释放，而是根据版本号去读取行的快照数据（记录在undo log中）</p>
<p>​	3）这样，事务中的查询操作返回的都是同一版本下的数据，解决了不可重复读问题。</p>
<p>​	4）虽然该隔离级别下解决了不可重复读问题，但理论上会导致另一个问题：幻读（Phantom Read）。</p>
<p>​	5）一个事务在执行过程中，另一个事物对已有数据行的更改，MVCC机制可保障该事物读取到的原有数据行的内容相同</p>
<p>​	6）但并不能阻止另一个事务插入新的数据行，这就会导致该事物中凭空多出数据行，像出现了幻读一样，这便是幻读问题。</p>
<p><strong>4</strong> <strong>可串行读（SERIALIZABLE）</strong></p>
<p>​	1）这是事务的最高隔离级别，通过强制事务排序，使之不可能相互冲突，就是在每个读的数据行加上共享锁来实现</p>
<p>​	2）在该隔离级别下，可以解决前面出现的脏读、不可重复读和幻读问题，但也会导致大量的超时和锁竞争现象，一般不推荐使用</p>
<h2 id="锁">锁</h2>
<p><strong>1.</strong> <strong>乐观锁</strong></p>
<p><strong>定义：</strong></p>
<p>​	总是假设最好的情况，每次去拿数据的时候都认为别人不会修改，所以不会上锁，但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于<strong>读多写少</strong>的应用类型，这样可以提高吞吐量</p>
<ol>
<li>
<p>每次获取商品时，不对该商品加锁。</p>
</li>
<li>
<p>在更新数据的时候需要比较程序中的库存量与数据库中的库存量是否相等，如果相等则进行更新</p>
</li>
<li>
<p>反之程序重新获取库存量，再次进行比较，直到两个库存量的数值相等才进行数据更新。</p>
</li>
</ol>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e">#### 乐观锁实现加一操作代码</span>
<span style="color:#75715e"># 我们可以看到，只有当对数量-1操作时才会加锁，只有当程序中值和数据库中的值相等时才正真执行。</span>
<span style="color:#e6db74">&#39;&#39;&#39;
</span><span style="color:#e6db74">//不加锁
</span><span style="color:#e6db74">select id,name,stock where id=1;
</span><span style="color:#e6db74">//业务处理
</span><span style="color:#e6db74">begin;
</span><span style="color:#e6db74">update shop set stock=stock-1 where id=1 and stock=stock;
</span><span style="color:#e6db74">commit;
</span><span style="color:#e6db74">&#39;&#39;&#39;</span>
</code></pre></div><p><strong>2. 悲观锁</strong></p>
<p>​	总是假设最坏的情况，每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁，这样别人想拿这个数据就会阻塞直到它拿到锁（<strong>共享资源每次只给一个线程使用，其它线程阻塞，用完后再把资源转让给其它线程</strong>）。多用在<strong>写多读少</strong>中</p>
<ol>
<li>
<p>每次获取商品时，对该商品加排他锁。</p>
</li>
<li>
<p>也就是在用户A获取获取 id=1 的商品信息时对该行记录加锁，期间其他用户阻塞等待访问该记录。</p>
</li>
</ol>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e">#### 悲观锁实现加一操作代码</span>
<span style="color:#75715e"># 我们可以看到，首先通过begin开启一个事物，在获得shop信息和修改数据的整个过程中都对数据加锁，保证了数据的一致性。</span>
<span style="color:#e6db74">&#39;&#39;&#39;
</span><span style="color:#e6db74">begin;
</span><span style="color:#e6db74">select id,name,stock as old_stock from shop  where id=1 for update;
</span><span style="color:#e6db74">update shop set stock=stock-1 where id=1 and stock=old_stock;
</span><span style="color:#e6db74">commit
</span><span style="color:#e6db74">&#39;&#39;&#39;</span>
</code></pre></div><p><strong>4.</strong> <strong>排它锁</strong></p>
<ol>
<li>
<p>排它锁又叫写锁，如果事务T对A加上排它锁，则其它事务都不能对A加任何类型的锁。获准排它锁的事务既能读数据，又能写数据。</p>
</li>
<li>
<p>用法 ： SELECT … FOR UPDATE</p>
</li>
</ol>
<p><strong>5.</strong> <strong>共享锁(share lock)</strong></p>
<ol>
<li>共享锁又叫读锁，如果事务T对A加上共享锁，则其它事务只能对A再加共享锁，不能加其它锁。</li>
<li>获准共享锁的事务只能读数据，不能写数据。</li>
<li>用法： SELECT … LOCK IN SHARE MODE;</li>
</ol>
<h2 id="sql语句">sql语句</h2>
<p><strong>1、导入原生sql模块</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">from</span> django.db <span style="color:#f92672">import</span> connection
</code></pre></div><p><strong>2、对结果集进行美化</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">dictfetchall</span>(cursor):

	<span style="color:#75715e"># 获取游标描述</span>
	desc <span style="color:#f92672">=</span> cursor<span style="color:#f92672">.</span>description

	<span style="color:#66d9ef">return</span> [

		dict(zip([col[<span style="color:#ae81ff">0</span>] <span style="color:#66d9ef">for</span> col <span style="color:#f92672">in</span> desc], row))

		<span style="color:#66d9ef">for</span> row <span style="color:#f92672">in</span> cursor<span style="color:#f92672">.</span>fetchall()

	]
</code></pre></div><p><strong>3、创建sql查询的函数</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UidFlow</span>(View):
	<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get</span>(self,request):
		uid <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>GET<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#34;uid&#34;</span>,None)

		<span style="color:#75715e"># 建立游标对象</span>
		cursor <span style="color:#f92672">=</span> connection<span style="color:#f92672">.</span>cursor()

		<span style="color:#75715e"># 执行sql语句(a.id,a.name,a.create_time是要给前台传数据库字段)</span>
		cursor<span style="color:#f92672">.</span>execute(<span style="color:#e6db74">&#39;select a.id,a.name,a.create_time from goods a left join userflow b on a.id = b.gid where b.uid = </span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#39;</span> <span style="color:#f92672">%</span> str(uid))

		<span style="color:#75715e"># 获取结果</span>
		<span style="color:#75715e"># result = cursor.fetchall()</span>
		result <span style="color:#f92672">=</span> dictfetchall(cursor)

		<span style="color:#75715e"># 返回结果 手动序列化</span>
		<span style="color:#66d9ef">return</span> HttpResponse(json<span style="color:#f92672">.</span>dumps(result,ensure_ascii<span style="color:#f92672">=</span>False,indent<span style="color:#f92672">=</span><span style="color:#ae81ff">4</span>,default<span style="color:#f92672">=</span>str),content_type<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;application/json&#39;</span>)
</code></pre></div>
</div>


    </main>

    
  </body>
</html>
